home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 420_01 / pi.c < prev    next >
C/C++ Source or Header  |  1994-02-21  |  16KB  |  725 lines

  1. /*
  2. //    Pi.cc -- pi$@%U%)!<%^%C%H2hA|$r07$&(J
  3. //
  4. //        created    in 3/21/1993
  5. //        revised    in 2/13/1994
  6. */
  7.  
  8. #include    <stdio.h>
  9. #include    <stdlib.h>
  10. #include    "defs.h"
  11. #include    "Pi.h"
  12. #include    "Pic.h"
  13.  
  14. static unsigned char    ColorTable[16 + 1][16 + 1];
  15. static unsigned char    *ColorTable256;
  16. static int     PreviousColor;
  17. static int     RestLength;
  18. static unsigned char    *Screen2;
  19. static int     PiMode;
  20. static int     PiXRatio, PiYRatio;
  21. static int     PiPlaneSize;
  22. static int     (*ReadColor)();
  23. static void     (*WriteColor)( int Previous, int Color );
  24.  
  25. void    ExpandPi();
  26. int     PiReadLength();
  27. int     PiReadColor16();
  28. int     PiReadColor256();
  29. void    CompressPi();
  30. void    PiWriteLength( int n );
  31. void    PiWriteColor16( int Previous, int Color );
  32. void    PiWriteColor256( int Previous, int Color );
  33. int     Search( unsigned char *s1, int offset );
  34. void    ColorTableInitialize();
  35.  
  36. void    PiLoad()
  37. {
  38.     int     i, OldWidth, x, y;
  39.     int     Limit;
  40.  
  41.     if ( fp == NULL && (fp = fopen( File, "rb" )) == NULL )
  42.     error ("%s: No such file");
  43.     AllocateBuffer();
  44.     BitBufferLength = 0;
  45.     PicBitLoad (8);
  46.     if ( PicWord != 'P' )
  47.     error ("%s: Is not pi format");
  48.     PicBitLoad (8);
  49.     if ( PicWord != 'i' )
  50.     error ("%s: Is not pi format");
  51.     for ( i = 0; i < 16384; i++ ) {
  52.     PicBitLoad (8);
  53.     if ( PicWord == 0x1a )
  54.         break;
  55.     }
  56.     if ( i == 16384 )
  57.     error ("%s: Is not pi format");
  58.     for ( i = 0; i < 16384; i++ ) {
  59.     PicBitLoad (8);
  60.     if ( PicWord == 0 )
  61.         break;
  62.     }
  63.     if ( i == 16384 )
  64.     error ("%s: Is not pi format");
  65.     PicBitLoad (8);
  66.     if ( (PiMode = PicWord) & ~0x80 )
  67.     error ("%s: Unknown pi-mode");
  68.     PicBitLoad (8);
  69.     PiXRatio = PicWord;
  70.     PicBitLoad (8);
  71.     PiYRatio = PicWord;
  72.     if ( PiXRatio == 0 || PiYRatio == 0 )
  73.     PiXRatio = PiYRatio = 1;
  74.     PicBitLoad (8);
  75.     if ( (PiPlaneSize = PicWord) != 4 && PiPlaneSize != 8 )
  76.     error ("%s: Irregal place size");
  77.     if ( PiPlaneSize == 8 ) {
  78.     if ( (ColorTable256 = (unsigned char*)malloc (65536 + 16)) == NULL )
  79.         error ("%s: Insufficient memory");
  80.     }
  81.     else
  82.     ColorTable256 = NULL;
  83.     PicBitLoad (8);
  84.     PicBitLoad (8);
  85.     PicBitLoad (8);
  86.     PicBitLoad (8);
  87.     PicBitLoad (16);
  88.     for ( i = PicWord; i > 0; i-- )
  89.     PicBitLoad (8);
  90.     PicBitLoad (16);
  91.     Width = PicWord;
  92.     PicBitLoad (16);
  93.     Height = PicWord;
  94.     if ( Screen != NULL )
  95.     free (Screen);
  96.     if ( (Screen = (int16*)malloc ((Size = Width * Height * PiXRatio * PiYRatio * 2) + 64)) == NULL )
  97.     error ("%s: Insufficient memory");
  98.     if ( (Screen2 = (unsigned char*)malloc (Width * (Height + 2) + 64)) == NULL )
  99.     error ("%s: Insufficient memory");
  100.     for ( i = 0; i < Width * (Height + 2); i++ )
  101.     Screen2[i] = 0;
  102.     if ( PiMode & 0x80 ) {
  103.     if ( PiPlaneSize == 4 ) {
  104.         for ( i = 0; i < 16; i++ ) {
  105.         Red[i] = ((i & 2)? 1 : 0) * (1 + (i > 7)) * 16 - 1;
  106.         Green[i] = ((i & 4)? 1 : 0) * (1 + (i > 7)) * 16 - 1;
  107.         Blue[i] = ((i & 1)? 1 : 0) * (1 + (i > 7)) * 16 - 1;
  108.         }
  109.     }
  110.     else {
  111.         for ( i = 0; i < 256; i++ ) {
  112.         Red[i] = ((i >> 2) & 7) << 2;
  113.         Green[i] = (i >> 5) << 2;
  114.         Blue[i] = (i & 3) << 3;
  115.         }
  116.     }
  117.     }
  118.     else {
  119.     for ( i = 0; i < (1 << PiPlaneSize); i++ ) {
  120.         PicBitLoad (8);
  121.         Red[i] = PicWord >> 3;
  122.         PicBitLoad (8);
  123.         Green[i] = PicWord >> 3;
  124.         PicBitLoad (8);
  125.         Blue[i] = PicWord >> 3;
  126.     }
  127.     }
  128.     for ( i = 0; i < 256; i++ )
  129.     Palette[i] = (Red[i] << 5) | (Green[i] << 10) | Blue[i];
  130.     ColorTableInitialize();
  131.     ExpandPi();
  132.     Limit = Width * (Height + 2);
  133.     for ( i = Width * 2; i < Limit; i++ )
  134.     Screen[i - Width * 2] = Palette[Screen2[i]];
  135.     if ( PiXRatio != 1 || PiYRatio != 1 ) {
  136.     OldWidth = Width;
  137.     Width = Width * PiYRatio;
  138.     Height = Height * PiXRatio;
  139.     for ( y = Height - 1; y >= 0; y-- ) {
  140.         for ( x = Width - 1; x >= 0; x-- ) {
  141.         Screen[x + y * Width] = Screen[x / PiYRatio + (y / PiXRatio) * OldWidth];
  142.         }
  143.     }
  144.     }
  145.     if ( PiPlaneSize == 8 )
  146.     free (ColorTable256);
  147.     free (Screen2);
  148.     free (BitBuffer);
  149.     if ( fp != stdin )
  150.     fclose (fp);
  151.     if ( PiPlaneSize == 4 )
  152.     MaxColorGuaranteed = 16;
  153.     else
  154.     MaxColorGuaranteed = 256;
  155. }
  156.  
  157. void    PiSave()
  158. {
  159.     int     i, j;
  160.     int32    HalfSize, MaxColor;
  161.  
  162.     for ( i = 0; i < 16; i++ )
  163.     Palette[i] = -1;
  164.     MaxColor = 0;
  165.     HalfSize = Size / 2;
  166.     if ( (Screen2 = (unsigned char*)malloc (Width * (Height + 2) + 16)) == NULL )
  167.     error ("%s: Insufficient memory");
  168.     for ( i = 0; i < HalfSize; i++ ) {
  169.     for ( j = 0; j < MaxColor; j++ )
  170.         if ( Palette[j] == Screen[i] )
  171.         break;
  172.     Screen2[i + Width * 2] = j;
  173.     if ( j == MaxColor ) {
  174.         Palette[j] = Screen[i];
  175.         MaxColor++;
  176.         if ( MaxColor > 256 )
  177.         error ("%s: Too many colors for pi format");
  178.     }
  179.     }
  180.     MaxColorGuaranteed = MaxColor;
  181.     if ( fp == NULL && (fp = fopen( File, "wb" )) == NULL )
  182.     error ("%s: No such file");
  183.     for ( i = 0; i < MaxColor; i++ ) {
  184.     Red[i] = ((Palette[i] >> 5) & 31) << 3;
  185.     Green[i] = (Palette[i] >> 10) << 3;
  186.     Blue[i] = (Palette[i] & 31) << 3;
  187.     }
  188.     AllocateBufferForWriting();
  189.     BitBufferLength = BitBufferSize;
  190.     BitLength = 8;
  191.     BitBufferPointer = BitBuffer;
  192.     if ( MaxColor <= 16 ) {
  193.     ColorTable256 = NULL;
  194.     PiPlaneSize = 4;
  195.     ColorTableInitialize();
  196.     PicBitWrite( 8, 'P' );    /* id; */
  197.     PicBitWrite( 8, 'i' );
  198.     PicBitWrite( 8, 26 );    /* eof; */
  199.     PicBitWrite( 8, 0 );    /* separator; */
  200.     PicBitWrite( 8, 0 );    /* mode; */
  201.     PicBitWrite( 8, 0 );    /* ratio; */
  202.     PicBitWrite( 8, 0 );    /* ratio; */
  203.     PicBitWrite( 8, 4 );    /* depth; */
  204.     PicBitWrite( 8, '-' );    /* machine code; */
  205.     PicBitWrite( 8, '-' );    /* machine code; */
  206.     PicBitWrite( 8, '-' );    /* machine code; */
  207.     PicBitWrite( 8, '-' );    /* machine code; */
  208.     PicBitWrite( 16, 0 );    /* reserved size; */
  209.     PicBitWrite( 16, Width );
  210.     PicBitWrite( 16, Height );
  211.     for ( i = 0; i < 16; i++ ) {
  212.         PicBitWrite( 8, Red[i] );
  213.         PicBitWrite( 8, Green[i] );
  214.         PicBitWrite( 8, Blue[i] );
  215.     }
  216.     }
  217.     else {
  218.     if ( (ColorTable256 = (unsigned char*)malloc (65536 + 16)) == NULL )
  219.         error ("%s: Insufficient memory");
  220.     PiPlaneSize = 8;
  221.     ColorTableInitialize();
  222.     PicBitWrite( 8, 'P' );    /* id; */
  223.     PicBitWrite( 8, 'i' );
  224.     PicBitWrite( 8, 26 );    /* eof; */
  225.     PicBitWrite( 8, 0 );    /* separator; */
  226.     PicBitWrite( 8, 0 );    /* mode; */
  227.     PicBitWrite( 8, 0 );    /* ratio; */
  228.     PicBitWrite( 8, 0 );    /* ratio; */
  229.     PicBitWrite( 8, 8 );    /* depth; */
  230.     PicBitWrite( 8, '-' );    /* machine code; */
  231.     PicBitWrite( 8, '-' );    /* machine code; */
  232.     PicBitWrite( 8, '-' );    /* machine code; */
  233.     PicBitWrite( 8, '-' );    /* machine code; */ 
  234.     PicBitWrite( 16, 0 );    /* reserved size; */
  235.     PicBitWrite( 16, Width );
  236.     PicBitWrite( 16, Height );
  237.     for ( i = 0; i < 256; i++ ) {
  238.         PicBitWrite( 8, Red[i] );
  239.         PicBitWrite( 8, Green[i] );
  240.         PicBitWrite( 8, Blue[i] );
  241.     }
  242.     }
  243.     CompressPi();
  244.     PicBufferWriteFlush();
  245.     if ( PiPlaneSize == 8 )
  246.     free (ColorTable256);
  247.     free (Screen2);
  248.     free (BitBuffer);
  249.     if ( fp != stdout )
  250.     fclose (fp);
  251. }
  252.  
  253. void    ColorTableInitialize()
  254. {
  255.     int     i, j;
  256.  
  257.     if ( PiPlaneSize == 4 ) {
  258.     for ( j = 0; j < 16; j++ )
  259.         for ( i = 0; i < 16; i++ )
  260.         ColorTable[j][i] = (16 - i + j) & 15;
  261.     }
  262.     else {
  263.     for ( j = 0; j < 256; j++ )
  264.         for ( i = 0; i < 256; i++ )
  265.         ColorTable256[i + j * 256] = (256 - i + j);
  266.     }
  267. }
  268.  
  269. void    ExpandPi()
  270. {
  271.     int     i;
  272.     int     c0, c1, c2, c3;
  273.     unsigned char    *Screen3, *p;
  274.     int     RestSize;
  275.     int     PreviousPosition, Position, Length;
  276.  
  277.     if ( PiPlaneSize == 4 )
  278.     ReadColor = PiReadColor16;
  279.     else
  280.     ReadColor = PiReadColor256;
  281.     PreviousColor = 0;
  282.     c0 = ReadColor();
  283.     c1 = ReadColor();
  284.     Screen3 = Screen2;
  285.     for ( i = 0; i < Width; i++ ) {
  286.     *Screen3++ = c0;
  287.     *Screen3++ = c1;
  288.     }
  289.     RestSize = Width * Height / 2;
  290.     for ( PreviousPosition = -1;; ) {
  291.     PicBitLoad (2);
  292.     if ( (Position = PicWord) == 3 ) {
  293.         PicBitLoad (1);
  294.         Position += PicWord;
  295.     }
  296.     if ( PreviousPosition == Position ) {
  297.         PreviousPosition = -1;
  298.         PreviousColor = *(Screen3 - 1);
  299.         for ( ;; ) {
  300.         *Screen3++ = ReadColor();
  301.         *Screen3++ = ReadColor();
  302.         RestSize--;
  303.         PicBitLoad (1);
  304.         if ( PicWord == 0 )
  305.             break;
  306.         }
  307.         continue;
  308.     }
  309.     PreviousPosition = Position;
  310.     if ( (Length = PiReadLength()) <= 0 )
  311.         continue;
  312.     if ( (RestSize -= Length) < 0 ) {
  313.         Length += RestSize;
  314.         RestSize = 0;
  315.     }
  316. #define    MoveMem(Source,Destination,Size)    {\
  317.     unsigned